package com.viking.controller;

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.viking.domain.BlockExceptResult;
import com.viking.service.OrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.concurrent.TimeUnit;

@RestController
@RequestMapping("/order")
public class OrderController {

    @Autowired
    private OrderService orderService;


    @RequestMapping("/add")
    public String add() {
        System.out.println("下单成功！");
        return "ok,下单成功！";
    }

    @RequestMapping("/get")
    public String get() {
        System.out.println("查询成功！");
        return "ok,查询成功！";
    }


    /**
     *  结合Sentinel控制面板 设置 QPS流控
     *  value  定义资源
     *   blockHandler 设置 流控降级后的处理方法（默认该方法必须声明在同一个类）
     *      如果不想在同一个类中，可以配合blockHandlerClass(指定处理方法所在的类)及blockHandler(指定处理方法的名字)两个属性使用
     *   fallback 当接口出现了异常，就可以交给fallback指定的方法进行处理
     *      如果不想在同一个类中。可以配合fallbackClass(指定处理方法所在的类)及fallback(指定处理方法的名字)两个属性使用
     *   blockHandler 如果和fallback同时指定了，则blockHandler优先级更高
     *      exceptionsToIgnore 排除哪些异常不处理
     *   不用 @SentinelResource的话，可设置全局流控拦截返回（MyBlockExceptionHandler）
     */
    @RequestMapping("/flow")
//    @SentinelResource(value = "flow",blockHandler = "flowBlockHandler")
    public String flow() {
        System.out.println("访问成功！");
        return "ok，访问成功！";
    }

    /**
     * 结合Sentinel控制面板 设置 线程数流控
     */
    @RequestMapping("/flowThread")
    @SentinelResource(value = "flowThead", blockHandler = "flowBlockHandler")
    public String flowThread() throws InterruptedException {
        TimeUnit.SECONDS.sleep(2);
        System.out.println("访问成功！");
        return "ok，访问成功！";
    }

    /**
     * 流控返回
     * 参数必须包含被流控方法所有参数，且必须有BlockException参数，且返回结果也必须一致
     */
    public String flowBlockHandler(BlockException blockException) {
        return "流控";
    }


    // 关联流控   访问/add 触发/get
    @RequestMapping("/test1")
    public BlockExceptResult test1() {
        return orderService.getUser(1);
    }

    // 关联流控  访问/add 触发/get
    @RequestMapping("/test2")
    public BlockExceptResult test2(){
        return orderService.getUser(1);
    }

    /**
     * 测试异常 熔断降级
     */
    @RequestMapping("/myErr")
    public String myErr(){
        int num=1/0;
        return "hello";
    }



    /**
     * 测试 热点规则，必须使用@SentinelResource
     */
    @RequestMapping("/get/{id}")
    @SentinelResource(value = "getById",blockHandler = "HotBlockHandler")
    public String getById(@PathVariable("id") Integer id) {
        System.out.println("正常访问");
        return "正常访问";
    }

    public String HotBlockHandler(@PathVariable("id") Integer id,BlockException e) {
        return "热点异常处理";
    }

}
